package com.wx.business.ma.service;

import com.alibaba.fastjson2.JSONObject;
import com.wx.adapter.api.domain.req.MaGetPhoneReq;
import com.wx.adapter.api.domain.req.MaSubscribeMessageReq;
import com.wx.adapter.http.wx.ma.MiniProgramMessageFeign;
import com.wx.adapter.http.wx.ma.MiniProgramUserFeign;
import com.wx.adapter.http.wx.ma.domain.dto.MaSubscribeSendResultDTO;
import com.wx.adapter.http.wx.ma.domain.dto.MiniprogramPhoneDTO;
import com.wx.adapter.http.wx.ma.domain.dto.PhoneInfo;
import com.wx.adapter.http.wx.ma.domain.dto.SnsJsCode2sessionDTO;
import com.wx.adapter.http.wx.ma.domain.req.SubscribeMessageDTO;
import com.wx.adapter.http.wx.ma.service.MiniProgramService;
import com.wx.infrastructure.enums.ErrorCodeEnum;
import com.wx.infrastructure.exception.DefaultBizException;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Arrays;
import java.util.Base64;

/**
 * wx_back_end
 *
 * @Auther: cheng.tang
 * @Date: 2023/2/28 10:00 PM
 * @Description:
 */
@Service
@Slf4j
public class MaUserServiceImpl implements MaUserService {

    @Autowired
    private MiniProgramService miniProgramService;

    @Autowired
    private MiniProgramUserFeign miniProgramUserFeign;

    @Autowired
    private MiniProgramMessageFeign miniProgramMessageFeign;

    @Override
    public PhoneInfo getPhone(MaGetPhoneReq maGetPhoneReq) {
        String token = miniProgramService.getAccessToken();
        MiniprogramPhoneDTO miniprogramPhoneDTO = miniProgramUserFeign.getuserphonenumber(token, maGetPhoneReq.buildCode2PhoneReq());
        return miniprogramPhoneDTO.getPhoneInfo();
    }


    @Override
    public PhoneInfo decryptPhone(String sessionKey, String encryptedData, String iv) {
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] sessionKeyByte = decoder.decode(sessionKey);
        byte[] dataByte = decoder.decode(encryptedData);
        byte[] ivByte = decoder.decode(iv);
        try {
            int base = 16;
            if (sessionKeyByte.length % base != 0) {
                int groups = sessionKeyByte.length / base + 1;
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(sessionKeyByte, 0, temp, 0, sessionKeyByte.length);
                sessionKeyByte = temp;
            }
            /**
             * 初始化
             */
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec spec = new SecretKeySpec(sessionKeyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, StandardCharsets.UTF_8);
                return JSONObject.parseObject(result, PhoneInfo.class);
            }
            log.warn("解密失败 解决后的数据为空");
            throw new DefaultBizException(ErrorCodeEnum.FAIL.setMsg("解密失败:解决后的数据为空"));
        } catch (Exception e) {
            log.warn("decryptPhone sessionKey {} encryptedData {} iv {}  msg {}", sessionKey, encryptedData, iv, e.getMessage());
            throw new DefaultBizException(ErrorCodeEnum.FAIL.setMsg(e.getMessage()));
        }
    }


    @Override
    public MaSubscribeSendResultDTO sendSubscribeMessage(MaSubscribeMessageReq req) {
        SnsJsCode2sessionDTO snsJsCode2sessionDTO = miniProgramService.snsJscode2session(req.getWxLoginJsCode());
        SubscribeMessageDTO subscribeMessageDTO = new SubscribeMessageDTO();
        BeanUtils.copyProperties(req, subscribeMessageDTO);
        subscribeMessageDTO.setTouser(snsJsCode2sessionDTO.getOpenid());
        String token = miniProgramService.getAccessToken();
        return miniProgramMessageFeign.messageSubscribeSend(token, subscribeMessageDTO);
    }


}
